using System;
using dnAnalytics.Statistics.Distributions;
using NUnit.Framework;

namespace dnAnalytics.Tests.Statistics.Distributions
{
    [TestFixture]
    public class GammaTests
    {
        private const double mAcceptableError = 1e-12;

        [Test]
        public void GammaTest()
        {
            Gamma gamma = new Gamma(10.0, 3.0);

            Assert.AreEqual(gamma.Shape, 10.0);
            Assert.AreEqual(gamma.InvScale, 3.0);

            Assert.AreEqual(10.0 / 3.0, gamma.Mean, mAcceptableError);
            Assert.AreEqual(System.Math.Sqrt(10.0) / 3.0, gamma.StdDev, mAcceptableError);
            Assert.AreEqual(10.0 / 9.0, gamma.Variance, mAcceptableError);
            Assert.AreEqual(3.0, gamma.Mode, mAcceptableError);

            Assert.AreEqual(0.008101511794677, gamma.Density(1.0), mAcceptableError);
            Assert.AreEqual(0.206515467061587, gamma.Density(2.0), mAcceptableError);

            Assert.AreEqual(-4.815704593400866, gamma.DensityLn(1.0), mAcceptableError);
            Assert.AreEqual(-1.577379968361357, gamma.DensityLn(2.0), mAcceptableError);

            Assert.AreEqual(0.001102488130115, gamma.CumulativeDistribution(1.0), mAcceptableError);
            Assert.AreEqual(0.930146339300625, gamma.CumulativeDistribution(5.0), mAcceptableError);
            Assert.AreEqual(0.999992878249137, gamma.CumulativeDistribution(10.0), mAcceptableError);
        }

        [Test]
        public void GetSetRNG()
        {
            Gamma gamma = new Gamma(10.0, 3.0);

            // Try getting the random number generator.
            System.Random rnd = gamma.RandomNumberGenerator;
            // Try setting the random number generator.
            gamma.RandomNumberGenerator = new System.Random();
        }

        [Test]
        public void TrySampler()
        {
            Gamma gamma = new Gamma(10.0, 3.0);

            double s = gamma.Sample();
            double[] t = gamma.Sample(2);

            double v = Gamma.Sample(new System.Random(), 10.0, 3.0);
            double[] w = Gamma.Sample(new System.Random(), 2, 10.0, 3.0);
        }

        [TestCase(-1.0, 10.0, ExpectedException = typeof(ArgumentOutOfRangeException))]
        [TestCase(1.0, -10.0, ExpectedException = typeof(ArgumentOutOfRangeException))]
        public void InvalidParams(double a, double b)
        {
            Gamma g = new Gamma(a, b);
        }
    }
}